﻿using SwyishChess.Domain.Piece;

namespace SwyishChess.Service
{
    public class SpecialMoveService : ISpecialMoveService
    {
        private const int CHESS_BOARD_ROW = 8;
        private const int CHESS_BOARD_COLUMN = 8;

        private const int BLACK_PLAYER = 2;

        /// <summary>
        /// Do actually promotion of a pawn
        /// </summary>
        /// <param name="chessPieces">Chess pieces array</param>
        /// <param name="type">Type the pawn is transforming to</param>
        /// <param name="cp">The pawn we are upgrading</param>
        /// <param name="owningPlayerID">The color of pawn</param>
        /// <returns>Upgraded chess piece</returns>
        public ChessPiece DoPawnPromotion(ChessPiece[,] chessPieces, string type, ChessPiece cp, int owningPlayerID, out ChessPiece affectedPiece)
        {
            affectedPiece = null;
            ChessPiece newCP = GetNewChessPieceInstance(type, owningPlayerID);

            // Search where the current chess piece is at
            for (int row = 0; row < CHESS_BOARD_ROW; row++)
            {
                for (int column = 0; column < CHESS_BOARD_COLUMN; column++)
                {
                    if (cp == chessPieces[row, column])
                    {
                        affectedPiece = chessPieces[row, column];
                        // Replace it with the newly created chess piece
                        chessPieces[row, column] = newCP;
                    }
                }
            }

            return newCP;
        }

        /// <summary>
        /// Creates a new chess piece based on the type and owner
        /// </summary>
        /// <param name="type">Name of the chess piece</param>
        /// <param name="owningPlayerID">Player ID of the owner</param>
        /// <returns>Newly create chess piece object</returns>
        private ChessPiece GetNewChessPieceInstance(string type, int owningPlayerID)
        {
            switch (type)
            {
                case "Rook":
                    return new Rook(owningPlayerID);
                case "Knight":
                    return new Knight(owningPlayerID);
                case "Queen":
                    return new Queen(owningPlayerID);
                case "Bishop":
                    return new Bishop(owningPlayerID);
                default:
                    return null;
            }
        }

        /// <summary>
        /// Do actually castling
        /// </summary>
        /// <param name="chessPieces">Chess pieces array</param>
        /// <param name="cp">Chess piece doing the castling</param>
        /// <param name="previousCol">Chess piece's previous column location</param>
        /// <param name="newCol"></param>
        /// <param name="affectedPiece"></param>
        public void DoCastling(ChessPiece[,] chessPieces, ChessPiece cp, int previousCol,
            int newCol, out ChessPiece affectedPiece)
        {
            int row;

            // Search for the chess piece and stop immediately if found
            for (row = 0; row < CHESS_BOARD_ROW; row += 7)
            {
                if (chessPieces[row, 2] == cp || chessPieces[row, 6] == cp)
                {
                    break;
                }
            }

            // If the movement was to left
            if (previousCol - newCol > 0)
            {
                // Move rook to the right of the King
                affectedPiece = chessPieces[row, 0];
                chessPieces[row, newCol + 1] = chessPieces[row, 0];
                chessPieces[row, 0] = null;
            }
            // if the movement was to right
            else
            {
                // Move rook to the left of the King
                affectedPiece = chessPieces[row, 0];
                chessPieces[row, newCol - 1] = chessPieces[row, 7];
                chessPieces[row, 7] = null;
            }
        }
        /// <summary>
        /// Do actually en passant
        /// </summary>
        /// <param name="chessPieces">Chess pieces array</param>
        /// <param name="cp">Chess piece doing the en passant</param>
        /// <param name="capturedPiece">Chess piece captured by en passant</param>
        public void DoEnPassant(ChessPiece[,] chessPieces, ChessPiece cp, out ChessPiece capturedPiece)
        {
            capturedPiece = null;

            for (int row = 0; row < CHESS_BOARD_ROW; row++)
            {
                for (int col = 0; col < CHESS_BOARD_COLUMN; col++)
                {
                    // Locate the chess piece
                    if (chessPieces[row, col] == cp)
                    {
                        // Depending on the color of the player decide
                        if (cp.OwningPlayerId == BLACK_PLAYER)
                        {
                            // Captures the chess piece
                            capturedPiece = chessPieces[row - 1, col];
                            chessPieces[row - 1, col] = null;
                        }
                        else
                        {
                            capturedPiece = chessPieces[row + 1, col];
                            chessPieces[row + 1, col] = null;
                        }
                    }
                }
            }
        }
    }
}
